const { FileModel, UploadModel, HomeWorkModel, StudentWorkModel } = require("../model");
const fs = require("fs").promises; // 使用fs的promises API进行异步操作
const { promisify } = require("util");
const fs2 = require("fs");
const existsSync = promisify(fs2.existsSync);
const rename = promisify(fs2.rename);
const unlink = promisify(fs2.unlink);
const path = require("path");
const rimraf = require("rimraf");
const iconv = require("iconv-lite");
// 创建文件夹的函数
async function createDirectory(dirPath) {
  try {
    await fs.mkdir(dirPath, { recursive: true }); // 使用recursive: true可以创建多级目录
  } catch (err) {
    console.error(`Error creating directory: ${err}`);
    throw err; // 如果发生错误，重新抛出以便外部处理
  }
}
let pathArr = [];
//递归获取路径
async function getPath(parentId) {
  if (parentId === "0") {
    return;
  }
  let result = await FileModel.findOne({ _id: parentId });
  pathArr.unshift(result.name);
  await getPath(result.parentId);
}
//转换单位
function formatFileSize(sizeBytes) {
  if (sizeBytes === 0) return "0 B";
  const units = ["B", "KB", "MB", "GB", "TB"];
  let i = 0;
  while (sizeBytes >= 1024) {
    sizeBytes /= 1024;
    ++i;
  }
  return `${sizeBytes.toFixed(2)} ${units[i]}`;
}
function shouldConvertEncoding(fileName) {
  // 使用正则表达式检查文件名是否只包含基本的ASCII字符（不包括中文字符）
  // 如果包含非ASCII字符（如中文字符），则需要进行编码转换
  const asciiOnlyRegex = /^[\x00-\x7F]+$/;
  return !asciiOnlyRegex.test(fileName);
}
//创建文件夹
exports.createFolder = async (req, res) => {
  let { name, parentId } = req.body;
  if (!name) {
    return res.status(400).json({
      code: 400,
      message: "文件夹名称不能为空",
      data: null,
    });
  }
  parentId = parentId ? parentId : "0";
  //判断parentId是否为0，如果为0，就直接在public下创建文件夹，如过不为0，就先查询数据库中对应的文件夹，然后再对应文件夹下进行创建
  if (parentId === "0") {
    //判断文件夹是否重名
    let result = await FileModel.findOne({ name: name, parentId: parentId });
    if (result) {
      return res.status(400).json({
        code: 400,
        message: "文件夹名称已存在",
        data: null,
      });
    }
    try {
      let dbBack = new FileModel({
        name: name,
        parentId: parentId,
      });
      dbBack.save();
      let folderPath = path.join(__dirname, "../public", name); // 根据您的项目结构进行调整

      await createDirectory(folderPath);
      return res.status(200).json({
        code: 200,
        message: "文件夹创建成功",
        data: null,
      });
    } catch (error) {
      return res.status(500).json({
        code: 500,
        message: "内部服务器错误" + error.message,
        data: null,
      });
    }
  } else {
    //判断文件夹是否重名
    let result = await FileModel.findOne({ name: name, parentId: parentId });
    if (result) {
      return res.status(400).json({
        code: 400,
        message: "文件夹名称已存在",
        data: null,
      });
    }
    //查询数据库中对应的文件夹
    let parentFolder = await FileModel.findOne({ _id: parentId });
    if (!parentFolder) {
      return res.status(400).json({
        code: 400,
        message: "父文件夹不存在",
        data: null,
      });
    }
    try {
      await getPath(parentId);

      let folderPath = path.join(__dirname, "../public", ...pathArr, name); // 根据您的项目结构进行调整

      await createDirectory(folderPath);
      let dbBack = new FileModel({
        name: name,
        parentId: parentId,
      });
      dbBack.save();
      pathArr = [];

      return res.status(200).json({
        code: 200,
        message: "文件夹创建成功",
        data: null,
      });
    } catch (error) {
      return res.status(500).json({
        code: 500,
        message: "内部服务器错误" + error.message,
        data: null,
      });
    }
  }
};
//获取文件夹列表
exports.getFolderList = async (req, res) => {
  try {
    let result = await FileModel.find();
    return res.status(200).json({
      code: 200,
      message: "文件夹列表获取成功",
      data: result,
    });
  } catch (error) {
    return res.status(500).json({
      code: 500,
      message: "内部服务器错误" + error.message,
      data: null,
    });
  }
};
//修改文件夹名称
exports.renameFolder = async (req, res) => {
  let { id, name } = req.body;
  if (!id || !name) {
    return res.status(400).json({
      code: 400,
      message: "参数不完整",
      data: null,
    });
  }
  let result = await FileModel.findOne({ _id: id });
  let result2 = await FileModel.findOne({
    name: name,
    parentId: result.parentId,
  });
  if (result2) {
    return res.status(400).json({
      code: 400,
      message: "文件夹名称已存在",
      data: null,
    });
  }
  try {
    result.name = name;
    await getPath(id);

    let folderPath = path.join(__dirname, "../public", ...pathArr);
    pathArr[pathArr.length - 1] = name;
    let folderPath2 = path.join(__dirname, "../public", ...pathArr);
    pathArr = [];
    await fs.rename(folderPath, folderPath2);
    await result.save();
    return res.status(200).json({
      code: 200,
      message: "文件夹名称修改成功",
      data: null,
    });
  } catch (error) {
    return res.status(500).json({
      code: 500,
      message: "内部服务器错误" + error.message,
      data: null,
    });
  }
};
//删除文件夹
exports.deleteFolder = async (req, res) => {
  let { id , fileId } = req.query;
  const { password } = req.body;
  if (!id || !password) {
    return res.status(400).json({
      code: 400,
      message: "参数不完整",
      data: null,
    });
  }
  if (req.user.teaPassword) {
    if (password != req.user.teaPassword) {
      return res.status(400).json({
        code: 400,
        message: "密码错误",
        data: null,
      });
    }
  } else {
    if (password != req.user.password) {
      return res.status(400).json({
        code: 400,
        message: "密码错误",
        data: null,
      });
    }
  }
  let parentInfo = await FileModel.findOne({
    _id:id
  })
  let workfile = await HomeWorkModel.findOne({
    name:parentInfo.name
  })
  console.log(parentInfo);
  console.log(workfile);
  console.log(fileId);
  if(workfile&&workfile.classId!==''&&!fileId) {
      return res.status(400).json({
        code: 400,
        message: "此文件夹为作业文件夹，如果要删除，请在作业管理中删除作业",
        data: null,
      });
  }

  try {
    await getPath(id);
    let folderPath = path.join(__dirname, "../public", ...pathArr);
    pathArr = [];

    rimraf.sync(folderPath);
    // await rimraf.sync(folderPath);
    await FileModel.deleteMany({ parentId: id });
    await FileModel.deleteOne({ _id: id });
    await UploadModel.deleteMany({ parentId: id });
    return res.status(200).json({
      code: 200,
      message: "文件夹删除成功",
      data: null,
    });
  } catch (error) {
    return res.status(500).json({
      code: 500,
      message: "内部服务器错误" + error.message,
      data: null,
    });
  }
};

//上传文件
exports.uploadFile = async (req, res) => {
  const { parentId } = req.query;
  if (!parentId) {
    return res.status(400).json({
      code: 400,
      message: "参数不完整",
      data: null,
    });
  }
  if (!req.file) {
    return res.status(400).json({
      code: 400,
      message: "文件上传失败或者没有文件上传",
      data: null,
    });
  }

  let fileName = shouldConvertEncoding(req.file.originalname)
    ? iconv.decode(iconv.encode(req.file.originalname, "ISO-8859-1"), "utf8")
    : req.file.originalname;
  let fileType = fileName.split(".").pop();
  let name = req.file.filename;
  let parentInfo = await FileModel.findOne({
    _id:parentId
  })
  let workfile = await HomeWorkModel.findOne({
    name:parentInfo.name
  })
  console.log(workfile);
  console.log(parentInfo);
  if(workfile&&workfile.classId!==''&&!req.work) {
    return res.status(400).json({
      code: 400,
      message: "此文件夹为作业文件夹，不可上传文件，如要上传，请前往作业管理上传作业",
      data: null,
    })
  }
  try {
    await getPath(parentId);
    let originalFilePath = path.join(__dirname, "../public/uploads", name);
    let newFilePath = path.join(__dirname, "../public", ...pathArr, fileName);
    let paths = pathArr.join("/");
    pathArr = [];
    // 确保目标文件夹存在
    // if (! (path.dirname(newFilePath))) {
    //   await fs.mkdir(path.dirname(newFilePath), { recursive: true });
    // }

    let result = await UploadModel.findOne({
      fileName: fileName,
      parentId: parentId,
    });

    if (result) {
      return res.status(400).json({
        code: 400,
        message: "文件名称已存在",
        data: null,
      });
    }
    console.log(req.file.size);
    await fs.mkdir(path.dirname(newFilePath), { recursive: true });
    // 使用 fs.promises.rename 移动并重命名文件
    await rename(originalFilePath, newFilePath);
    //删除原来的文件
    // await unlink(originalFilePath);
    let dbBack = new UploadModel({
      fileName: fileName,
      parentId: parentId,
      fileType: fileType,
      filePath: "127.0.0.1:3000/" + paths + "/" + fileName,
      fileSize: formatFileSize(req.file.size),
    });
    await dbBack.save();
    if(req.work) {
      let homework = await StudentWorkModel.findOne({_id:req.work._id})
      homework.fileId = dbBack._id
      await homework.save()
    }
    return res.status(200).json({
      code: 200,
      message: "文件上传成功",
      data: null,
    });
  } catch (error) {
    return res.status(500).json({
      code: 500,
      message: "内部服务器错误" + error.message,
      data: null,
    });
  }
};
//获取对应文件夹下对应的文件
exports.getFiles = async (req, res) => {
  const { parentId, fileName = "", pageNo = 1, pageSize = 10 } = req.query;
  if (!parentId) {
    return res.status(400).json({
      code: 400,
      message: "参数不完整",
      data: null,
    });
  }
  try {
    let result = await UploadModel.find({
      parentId: parentId,
      fileName: new RegExp(fileName),
    })
      .skip((pageNo - 1) * pageSize)
      .limit(pageSize);
    let count = await UploadModel.find({
      parentId: parentId,
      fileName: new RegExp(fileName),
    }).countDocuments();
    return res.status(200).json({
      code: 200,
      message: "获取文件成功",
      data: {
        result,
        total: count,
      },
    });
  } catch (error) {
    return res.status(500).json({
      code: 500,
      message: "内部服务器错误" + error.message,
      data: null,
    });
  }
};
//删除文件
exports.deleteFile = async (req, res) => {
  let id = req.query.id;

  if (!id) {
    return res.status(400).json({
      code: 400,
      message: "参数不完整",
      data: null,
    });
  }
  let result = await UploadModel.findById(id);
  if (!result) {
    return res.status(400).json({
      code: 400,
      message: "文件不存在",
      data: null,
    });
  }
  let parentId = result.parentId;
  let fileName = result.fileName;

  let parentInfo = await FileModel.findOne({
    _id:parentId
  })
  let workfile = await HomeWorkModel.findOne({
    name:parentInfo.name
  })

  if(workfile&&workfile.classId!==''&&req.fileId=='') {
    return res.status(400).json({
      code: 400,
      message: "此文件夹为作业文件夹，不可删除，如要删除，请前往作业管理删除作业",
      data: null,
    })
  }
  try {
    await getPath(parentId);
    let filepath = path.join(__dirname, "../public", ...pathArr, fileName);
    pathArr = [];
    await unlink(filepath);
    await UploadModel.deleteOne({
      _id: id,
    });
    return res.status(200).json({
      code: 200,
      data: null,
      message: "删除成功",
    });
  } catch (error) {
    return res.status(500).json({
      code: 500,
      data: null,
      message: "内部服务器错误" + error.message,
    });
  }
};  
